package com.ea.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ea.admin.mapper.*;
import com.ea.admin.pojo.Enum.RoleCode;
import com.ea.admin.pojo.dto.AdminAccountDto;
import com.ea.admin.pojo.dto.AdminOperatingLogDto;
import com.ea.admin.pojo.po.AdminAccount;
import com.ea.admin.pojo.po.AdminRole;
import com.ea.admin.pojo.vo.account.*;
import com.ea.admin.service.AccountService;
import com.ea.admin.service.CompanyPermissionService;
import com.ea.admin.service.FunctionPermissionService;
import com.ea.admin.service.PermissionService;
import com.ea.common.result.BizException;
import com.ea.common.result.ErrorCode;
import com.ea.common.utils.ParamUtil;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class AccountServiceImpl implements AccountService {
    @Resource
    AdminAccountMapper adminAccountMapper;
    @Resource
    AdminOperatingLogMapper adminOperatingLogMapper;
    @Resource
    AdminRoleMapper adminRoleMapper;
    @Resource
    CompanyInfoMapper companyInfoMapper;
    @Resource
    DeptInfoMapper deptInfoMapper;
    @Resource
    CheckAccountService checkAccountService;
    @Resource
    CompanyPermissionService companyPermissionService;
    @Resource
    DeptPermissionServiceImpl deptPermissionService;
    @Resource
    PermissionService permissionService;
    @Resource
    FunctionPermissionService functionPermissionService;

    @Override
    public List<Long> getSuperAdminIdList() {
        LambdaQueryWrapper<AdminAccount> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AdminAccount::getAdminRoleId, 1);
        List<AdminAccount> adminAccountList = adminAccountMapper.selectList(wrapper);
        return adminAccountList.stream().map(AdminAccount::getAccountId).collect(Collectors.toList());
    }

    @Override
    public GetAdminRoleVo getAdminRole() {
        List<AdminRole> adminRoles = adminRoleMapper.selectList(null);
        GetAdminRoleVo result = new GetAdminRoleVo();
        result.setItems(parseAdminRoleListToVo(adminRoles));
        return result;
    }

    @Override
    public AdminAccount addAdmin(String username, String password, String rePassword, String name, String phoneNumber, Long adminRoleId) {

        // 1. 检查传入的password和rePassword是否相同，不相同的话，则报“密码和确认密码不一致”错误
        if (!password.equals(rePassword)) {
            throw new BizException(ErrorCode.USER_REGISTER_ERROR_PASSWORD_NOT_EQUALS);
        }

        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        String encodePassword = bCryptPasswordEncoder.encode(password);
        // 检查用户名是否已被使用
        LambdaQueryWrapper<AdminAccount> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AdminAccount::getUsername, username);
        AdminAccount userAccount = adminAccountMapper.selectOne(wrapper);
        if (userAccount != null) {
            throw new BizException(ErrorCode.USER_REGISTER_ERROR_ACCOUNT_EXISTS);
        }

        AdminAccount adminAccount = new AdminAccount();
        adminAccount.setUsername(username);
        adminAccount.setPassword(encodePassword);
        adminAccount.setPhoneNumber(phoneNumber);
        adminAccount.setAdminRoleId(adminRoleId);
        adminAccount.setName(name);
        adminAccount.setIsDel(0);
        adminAccount.setIsBlock(0);
        adminAccount.setRole("user");
        adminAccountMapper.insert(adminAccount);

        // 获得管理员对应角色的默认权限
        List<Integer> defaultPermissionCodeList = functionPermissionService.getDefaultFunctionPermissionCode(adminRoleId);
        // 为管理员添加默认功能权限
        functionPermissionService.addFunctionPermission(adminAccount.getAccountId(), defaultPermissionCodeList);
        // 为超级管理员添加所有单位权限
        if (adminRoleId == 1) {
            List<Long> allCompanyId = companyInfoMapper.getAllCompanyId();
            if (!allCompanyId.isEmpty()) {
                companyPermissionService.addCompanyPermission(
                        adminAccount.getAccountId(),
                        allCompanyId);
            }
            List<Long> allDeptId = deptInfoMapper.getAllDeptId();
            if (!allDeptId.isEmpty()) {
                deptPermissionService.addDeptPermission(
                        adminAccount.getAccountId(),
                        allDeptId);
            }
        }

        return adminAccount;
    }

    @Override
    public void createRootAdmin(String username, String password, String name, String phoneNumber) {
        // 检查用户名是否已被使用
        LambdaQueryWrapper<AdminAccount> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AdminAccount::getUsername, username);
        AdminAccount userAccount = adminAccountMapper.selectOne(wrapper);
        if (userAccount != null) {
            throw new BizException(ErrorCode.USER_REGISTER_ERROR_ACCOUNT_EXISTS);
        }

        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        String encodePassword = bCryptPasswordEncoder.encode(password);

        AdminAccount adminAccount = new AdminAccount();
        adminAccount.setUsername(username);
        adminAccount.setPassword(encodePassword);
        adminAccount.setPhoneNumber(phoneNumber);
        adminAccount.setAdminRoleId(1L);
        adminAccount.setName(name);
        adminAccount.setIsBlock(0);
        adminAccount.setIsDel(0);
        adminAccount.setRole("user");
        adminAccountMapper.insert(adminAccount);

        // 为超级管理员添加所有功能权限
        List<Integer> allPermission = functionPermissionService.getAllFunctionPermission();
        functionPermissionService.addFunctionPermission(
                adminAccount.getAccountId(),
                allPermission
        );
        // 为超级管理员添加所有单位权限
        List<Long> allCompanyId = companyInfoMapper.getAllCompanyId();
        companyPermissionService.addCompanyPermission(
                adminAccount.getAccountId(),
                allCompanyId
        );
        // 为超级管理员添加所有部门权限
        List<Long> allDeptId = deptInfoMapper.getAllDeptId();
        deptPermissionService.addDeptPermission(
                adminAccount.getAccountId(),
                allDeptId
        );
    }

    @Override
    public GetAdminListVo getAdminList(Long accountId, Integer page, Integer pageSize, String username, String name, String phoneNumber, List<Long> companyIdList, List<Long> deptIdList, List<Integer> adminRoleId) {
        if (adminRoleId == null || adminRoleId.isEmpty()) {
            // 查出所有
            adminRoleId = getAdminRole().getItems().stream().map(AdminRoleVo::getAdminRoleId).collect(Collectors.toList());
        }
        AdminAccount nowAdminAccount = adminAccountMapper.selectById(accountId);
        Integer roleId = nowAdminAccount.getAdminRoleId().intValue();
        // 如果是单位管理员，排除掉超级管理员。
        if ((roleId.equals(RoleCode.COMPANY_SUPER_ADMIN.getCode()) ||
                roleId.equals(RoleCode.COMPANY_ADMIN.getCode()))
        ) {
            adminRoleId.remove(RoleCode.SUPER_ADMIN.getCode());
        }
        // 如果是部门管理员，则去掉前面的两种
        if (roleId.equals(RoleCode.DEPT_SUPER_ADMIN.getCode()) ||
                roleId.equals(RoleCode.DEPT_ADMIN.getCode())) {
            adminRoleId.remove(RoleCode.SUPER_ADMIN.getCode());
            adminRoleId.remove(RoleCode.COMPANY_SUPER_ADMIN.getCode());
            adminRoleId.remove(RoleCode.COMPANY_ADMIN.getCode());
        }

        PermissionServiceImpl.PermissionList checked = permissionService
                .checkAndRefreshPermissionList(companyIdList, deptIdList, accountId);
        companyIdList = checked.companyIdList;
        deptIdList = checked.deptIdList;

        Page<AdminAccountDto> adminAccountPage = adminAccountMapper.selectAdminAccountDto(
                new Page<>(page, pageSize),
                username,
                name,
                phoneNumber,
                companyIdList,
                deptIdList,
                adminRoleId
        );
        GetAdminListVo result = new GetAdminListVo();
        result.setItems(parseAdminAccountListToVo(adminAccountPage.getRecords()));
        result.setTotal((int) (adminAccountPage.getTotal()));
        result.setPageSize((int) (adminAccountPage.getSize()));
        result.setCurrent((int) (adminAccountPage.getCurrent()));

        // 为每个管理员添加权限信息
        result.getItems().forEach(adminInfoVo -> {
            adminInfoVo.setFunctionPermissionVoList(
                    functionPermissionService.getFunctionPermissionByAccountId(
                            ParamUtil.parseId(adminInfoVo.getAccountId())
                    )
            );

            adminInfoVo.setCompanyPermissionList(
                    companyPermissionService.getCompanyPermission(
                            ParamUtil.parseId(adminInfoVo.getAccountId())
                    )
            );

            adminInfoVo.setDepartmentPermissionList(
                    deptPermissionService.getDeptPermission(
                            null,
                            ParamUtil.parseId(adminInfoVo.getAccountId())
                    )
            );
        });

        return result;
    }

    @Override
    public void editAdmin(Long accountId, String username, String name, String phoneNumber, Long adminRoleId) {
        AdminAccount adminAccount = checkAccountService.checkAdminAccount(accountId);
        if (!adminAccount.getName().equals(name)) {
            // 检查用户名是否唯一
            LambdaQueryWrapper<AdminAccount> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(AdminAccount::getUsername, username);
            AdminAccount userAccount = adminAccountMapper.selectOne(wrapper);
            if (userAccount != null && !userAccount.getAccountId().equals(accountId)) {
                throw new BizException(ErrorCode.USER_REGISTER_ERROR_ACCOUNT_EXISTS);
            }
            adminAccount.setUsername(username);
        }
        if (!adminAccount.getAdminRoleId().equals(adminRoleId)) {
            // 检查角色是否是单位联系人或部门联系人
            companyPermissionService.checkIsCompanyContact(adminAccount.getAccountId());
            deptPermissionService.checkIsDeptContact(adminAccount.getAccountId());
            adminAccount.setAdminRoleId(adminRoleId);
        }

        adminAccount.setName(name);
        adminAccount.setPhoneNumber(phoneNumber);
        adminAccountMapper.updateById(adminAccount);

        // 是否需要踢出管理员？
    }
    @Override
    public void blockAdmin(Long nowAccountId, Long accountId, Integer isBlock) {
        // 检查是否操作的是自己
        if (nowAccountId.equals(accountId)) {
            throw new BizException(ErrorCode.SYSTEM_RESOURCE_ADMIN_ACCOUNT_NOT_BLOCK_SELF);
        }
        // 检查管理员账户是否存在
        checkAccountService.checkAdminAccount(nowAccountId);

        // 检查被操作的管理员是否存在
        AdminAccount adminAccount = adminAccountMapper.selectById(accountId);
        if (adminAccount == null) {
            throw new BizException(ErrorCode.SYSTEM_RESOURCE_ADMIN_ACCOUNT_NOT_EXISTS);
        }
        adminAccount.setIsBlock(isBlock);
        adminAccountMapper.updateById(adminAccount);
        // 是否需要踢出管理员？
    }

    @Override
    public void deleteAdmin(Long nowAccountId, Long accountId) {
        // 检查是否操作的是自己。
        if (nowAccountId.equals(accountId)) {
            throw new BizException(ErrorCode.SYSTEM_RESOURCE_ADMIN_ACCOUNT_NOT_DELETE_SELF);
        }
        // 检查管理员账户是否存在
        checkAccountService.checkAdminAccount(accountId);

        adminAccountMapper.deleteById(accountId);
        // 删除功能权限
        functionPermissionService.deleteFunctionPermissionByAccountId(accountId);
        // 删除部门权限
        deptPermissionService.deleteDeptPermissionByAccountId(accountId);
        // 删除单位权限
        companyPermissionService.deleteCompanyPermissionByAccountId(accountId);
    }

    @Override
    public void editPassword(Long nowAccountId, Long accountId, String password, String rePassword) {
        // 检查是否操作的是默认管理员admin。
        if (nowAccountId.equals(1L)) {
            if(nowAccountId.equals(accountId)){
                throw new BizException(ErrorCode.SYSTEM_RESOURCE_ADMIN_ACCOUNT_NOT_EDIT_PASSWORD_SELF);
            }
        }
        // 验证前后密码是否一致
        if (!password.equals(rePassword)) {
            throw new BizException(ErrorCode.USER_REGISTER_ERROR_PASSWORD_NOT_EQUALS);
        }

        // 检查管理员账户是否存在
        if (adminAccountMapper.selectById(accountId) == null) {
            throw new BizException(ErrorCode.SYSTEM_RESOURCE_ADMIN_ACCOUNT_NOT_EXISTS);
        }

        AdminAccount adminAccount = new AdminAccount();
        adminAccount.setAccountId(accountId);
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        String encodePassword = bCryptPasswordEncoder.encode(password);
        adminAccount.setPassword(encodePassword);
        adminAccountMapper.updateById(adminAccount);
    }

    @Override
    public void editFunctionPermission(Long accountId, List<Integer> functionPermissionList) {
        // 检查管理员账户是否存在
        if (adminAccountMapper.selectById(accountId) == null) {
            throw new BizException(ErrorCode.SYSTEM_RESOURCE_ADMIN_ACCOUNT_NOT_EXISTS);
        }

        // 去除用户原有的功能权限
        functionPermissionService.deleteFunctionPermissionByAccountId(accountId);
        functionPermissionService.addFunctionPermission(accountId, functionPermissionList);
    }

    @Override
    public void editCompanyPermission(Long accountId, List<Long> companyPermissionList) {
        // 检查管理员账户是否存在
        checkAccountService.checkAdminAccount(accountId);

        // 检查用户是否有担任联系人的单位
        companyPermissionService.checkContactCompany(accountId, companyPermissionList);

        // 去除用户原有的单位权限
        companyPermissionService.deleteCompanyPermissionByAccountId(accountId);
        if (companyPermissionList == null || companyPermissionList.isEmpty()) {
            return;
        }
        companyPermissionService.addCompanyPermission(accountId, companyPermissionList);
    }

    @Override
    public void editDepartmentPermission(Long accountId, List<Long> deptPermissionList) {
        // 检查管理员账户是否存在
        checkAccountService.checkAdminAccount(accountId);

        // 检查用户是否有担任联系人的单位
        deptPermissionService.checkContactDept(accountId, deptPermissionList);

        // 去除用户原有的单位权限
        deptPermissionService.deleteDeptPermissionByAccountId(accountId);
        if (deptPermissionList == null || deptPermissionList.isEmpty()) {
            return;
        }
        deptPermissionService.addDeptPermission(accountId, deptPermissionList);
    }

    @Override
    public GetOperateLogVo getOperateLog(Integer page, Integer pageSize, String username, String name, Date startTime, Date endTime) {
        Page<AdminOperatingLogDto> adminOperatingLogs = adminOperatingLogMapper.getOperateLog(
                new Page<>(page, pageSize),
                username, name, startTime, endTime);
        GetOperateLogVo result = new GetOperateLogVo();
        result.setItems(parseAdminOperatingLogListToVo(adminOperatingLogs.getRecords()));
        result.setTotal((int) (adminOperatingLogs.getTotal()));
        result.setPageSize((int) (adminOperatingLogs.getSize()));
        result.setCurrent((int) (adminOperatingLogs.getCurrent()));
        return result;
    }


    private List<AdminRoleVo> parseAdminRoleListToVo(List<AdminRole> adminRoles) {
        return adminRoles.stream().map(this::parseAdminRoleToVo).collect(Collectors.toList());
    }

    private AdminRoleVo parseAdminRoleToVo(AdminRole adminRole) {
        AdminRoleVo adminRoleVo = new AdminRoleVo();
        adminRoleVo.setAdminRoleId(adminRole.getAdminRoleId().intValue());
        adminRoleVo.setAdminRoleName(adminRole.getAdminRoleName());
        return adminRoleVo;
    }

    private List<AdminOperatingLogVo> parseAdminOperatingLogListToVo(List<AdminOperatingLogDto> adminOperatingLogList) {
        return adminOperatingLogList.stream().map(this::parseAdminOperateLogToVo).collect(Collectors.toList());
    }

    private AdminOperatingLogVo parseAdminOperateLogToVo(AdminOperatingLogDto log) {
        AdminOperatingLogVo adminOperatingLogVo = new AdminOperatingLogVo();
        adminOperatingLogVo.setAccountId(log.getAccountId().toString());
        adminOperatingLogVo.setName(log.getName());
        adminOperatingLogVo.setUsername(log.getUsername());
        adminOperatingLogVo.setContent(log.getContent());
        adminOperatingLogVo.setOperatingTime(log.getOperatingTime());
        return adminOperatingLogVo;
    }

    private List<AdminInfoVo> parseAdminAccountListToVo(List<AdminAccountDto> adminAccountDtoList) {
        return adminAccountDtoList.stream().map(this::parseAdminAccountDtoToVo).collect(Collectors.toList());
    }

    private AdminInfoVo parseAdminAccountDtoToVo(AdminAccountDto adminAccount) {
        AdminInfoVo adminInfoVo = new AdminInfoVo();
        adminInfoVo.setAccountId(adminAccount.getAccountId().toString());
        adminInfoVo.setName(adminAccount.getName());
        adminInfoVo.setPhoneNumber(adminAccount.getPhoneNumber());
        adminInfoVo.setUsername(adminAccount.getUsername());
        adminInfoVo.setIsBlock(adminAccount.getIsBlock());
        adminInfoVo.setAdminRoleId(adminAccount.getAdminRoleId());
        adminInfoVo.setAdminRoleName(adminAccount.getAdminRoleName());
        return adminInfoVo;
    }

}
